package com.landerer.math;

public final class Complex {

	private final double re;
	private final double im;

	public Complex(final double re, final double im) {

		this.re = re;
		this.im = im;
	}

	public double realPart() {

		return this.re;
	}

	public double imaginaryPart() {

		return this.im;
	}

	public Complex add(final Complex c) {

		return new Complex(this.re + c.re, this.im + c.im);
	}

	public Complex subtract(final Complex c) {

		return new Complex(this.re - c.re, this.im - c.im);
	}

	public Complex multiply(final Complex c) {

		return new Complex(this.re * c.re - this.im * c.im, this.re * c.im + this.im * c.re);
	}

	public Complex divide(final Complex c) {

		final double tmp = c.re * c.re + c.im * c.im;
		return new Complex((this.re * c.re + this.im * c.im) / tmp, (this.im * c.re - this.re * c.im) / tmp);
	}

	@Override
	public boolean equals(final Object o) {

		if (o == this) {
			return true;
		}
		if (!(o instanceof Complex)) {
			return false;
		}

		Complex c = (Complex) o;
		return Double.compare(this.re, c.re) == 0 && Double.compare(this.im, c.im) == 0;
	}

	@Override
	public int hashCode() {

		int result = 17 + this.hashDouble(this.re);
		result = 31 * result + this.hashDouble(this.im);
		return result;
	}

	@Override
	public String toString() {

		return "(" + this.re + " + " + this.im + "i)";
	}

	private int hashDouble(final double value) {

		long longBits = Double.doubleToLongBits(value);
		return (int) (longBits ^ (longBits >>> 32));
	}

}
